package com.neu.utils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSA工具类
 */
public class RSAUtil {

    /**
     * 根据随机种子生产公钥和私钥并且保存到文件中，参数是公钥保存路径，私钥保存路径，以及种子字符串，这个种子字符串最好是随机的，不然会调用同一个公钥或者私钥
     */
    public static void generateKey(String publicKeyFilePath, String privateKeyFilePath, String seed) throws Exception {
        // 获取密钥生成器实例
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 初始化安全随机数生成器
        SecureRandom secureRandom = new SecureRandom(seed.getBytes());
        // 初始化密钥生成器
        keyPairGenerator.initialize(1024, secureRandom);
        // 生成密钥对
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        // 获取公钥，转成二进制，并写入文件中
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        writeFile(publicKeyFilePath, publicKeyBytes);
        // 获取私钥，转成二进制，并写入文件中
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        writeFile(privateKeyFilePath, privateKeyBytes);
    }


    /**
     * 读取公钥
     */
    public static PublicKey getPublicKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        // 创建公钥规范
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        // 获取密钥工厂实例，这是一个单例
        KeyFactory factory = KeyFactory.getInstance("RSA");
        // 调用generatePublic方法返回一个PublicKey对象
        return factory.generatePublic(spec);
    }

    /**
     * 读取私钥，用于生成token
     */
    public static PrivateKey getPrivateKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        // 创建私钥规范
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        // 获取密钥工厂实力，这是一个单例
        KeyFactory factory = KeyFactory.getInstance("RSA");
        // 调用generatePrivate方法返回一个PrivateKey对象
        return factory.generatePrivate(spec);
    }

    /**
     * 读取文件，读取写入公钥、私钥的文件，用于生成token
     */
    private static byte[] readFile(String fileName) throws Exception {
        return Files.readAllBytes(new File(fileName).toPath());
    }

    /**
     * 将生成的公钥、私钥写入文件中，保存在硬盘中，以后生成token不用生成新的公钥和私钥，直
     * 接用就好了
     */
    private static void writeFile(String destPath, byte[] bytes) throws IOException {
        File dest = new File(destPath);
        if (!dest.exists()) {
            dest.createNewFile();
        }
        Files.write(dest.toPath(), bytes);
    }
}